//float2int.h
#pragma once

#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include "fpu.h"

/** default MSVC implementation of the transformation is rather slow,
	these functions are faster */

/** sometimes a bit slower than QF2I, but does not require FPU power */
inline int float2int( const float &f ) 
{
    const int &iy = reinterpret_cast<const int&>(f);
    if( iy == 0 ) return 0;
    int exponent=((iy & 0x7f800000) >> 23)-127;
    int res;
    if( exponent < 0 ) {
        res = 0;
    } else {
        int mantissa = (iy & 0x007fffff) | 0x00800000;
        if( (exponent-=23) < 0 ) {
            res = (mantissa >> -exponent);
        } else {
            /* if exponent is too big - result is unpredictable */ 
            res = (mantissa << exponent);
        }
        if( iy&0x80000000 ) res=-res;
    }

    assert( res == int(f) );
    return res;
}

inline int round( const float &f ) 
{
    const int &iy = reinterpret_cast<const int&>(f);
    if( iy == 0 ) return 0;
    int exponent=((iy & 0x7f800000) >> 23)-126;
    int res;
    if( exponent < 0 ) {
        res = 0;
    } else {
        int mantissa = (iy & 0x007fffff) | 0x00800000;
        if( (exponent-=24) < 0 ) {
            res = ((mantissa >> (-1-exponent)) + 1) >> 1;
        } else {
            /* if exponent is too big - result is unpredictable */ 
            //no rounding since precision of int is more than one of float
            res = (mantissa << exponent);
        }
        if( iy&0x80000000 ) res=-res;
    }

    assert( ((res>=0 && f>=0) || (res<=0 && f<=0)) && abs(res) == int(fabs(f)+0.5) );
    return res;
}

